// ****************************************************************
// Copyright 2012, Stephan Burguchev
// e-mail: me@sburg.net
// ****************************************************************
// *
using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using Updater.Utils;
using Version = Updater.Utils.Version;

namespace Updater.Common
{
    [XmlRoot("configuration")]
    [Serializable]
    public class Configuration
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Configuration" /> class.
        /// </summary>
        /// <remarks>
        ///     The properties is set with initial values according the following logic.
        ///     <para>
        ///         <see cref="CurrentVersion" /> is set to the parsed value of an AssemblyVersion
        ///         attribute of the calling assembly.
        ///     </para>
        ///     <para>
        ///         <see cref="UpdaterCacheDirectory" /> is set to the value
        ///         '${LocalApplicationData}\${AssemblyProduct}\UpdatesCache' where ${LocalApplicationData}
        ///         is the local appplication data directory and ${AssemblyProduct} is the value of an
        ///         AssemblyProduct attribute of the calling assembly.
        ///     </para>
        ///     <para>
        ///         <see cref="ApplicationDirectory" /> is set to the directory locating the calling assembly file.
        ///     </para>
        ///     <para>
        ///         <see cref="ApplicationFilename" /> is set to the filename of the calling assembly file.
        ///     </para>
        /// </remarks>
        public Configuration()
        {
            Assembly assembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();
            var reader = new AssemblyAttributesReader(assembly);

            // version
            Version version;
            Version.TryParse(reader.AssemblyVersion, out version);
            this.CurrentVersion = version;

            // updatesCacheDir
            string appData = Environment.GetFolderPath(
                Environment.SpecialFolder.LocalApplicationData,
                Environment.SpecialFolderOption.Create);
            string applicationTitle = reader.AssemblyProduct;
            this.UpdaterCacheDirectory = Path.Combine(appData, applicationTitle, "UpdatesCache");

            try
            {
                // appDir
                this.ApplicationDirectory = Path.GetDirectoryName(assembly.Location);

                // appName
                this.ApplicationFilename = Path.GetFileName(assembly.Location);
            }
            catch (NotSupportedException)
            {
            }
            catch (ArgumentException)
            {
            }
            catch (PathTooLongException)
            {
            }
        }

        /// <summary>
        ///     Gets or sets a path to the application directory.
        /// </summary>
        /// <value>
        ///     The application directory.
        /// </value>
        [XmlElement("application-directory")]
        public string ApplicationDirectory { get; set; }

        /// <summary>
        ///     Gets or sets the application filename relative to the application directory.
        /// </summary>
        /// <value>
        ///     The application filename.
        /// </value>
        [XmlElement("application-filename")]
        public string ApplicationFilename { get; set; }

        [XmlElement("current-version")]
        public Version CurrentVersion { get; set; }

        /// <summary>
        ///     Gets or sets a path to the directory containing the application updater cache.
        /// </summary>
        /// <value>
        ///     The updater cache directory.
        /// </value>
        [XmlElement("updater-cache-directory")]
        public string UpdaterCacheDirectory { get; set; }

        [XmlIgnore]
        public Uri UpdatesFeedUri { get; set; }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [XmlElement("updates-feed-uri")]
        public string UpdatesFeedUriString
        {
            get
            {
                return this.UpdatesFeedUri == null ? null : this.UpdatesFeedUri.ToString();
            }
            set
            {
                this.UpdatesFeedUri = value == null ? null : new Uri(value);
            }
        }
    }
}
